package com.lbw.Client.proxy;


import com.lbw.Client.circuitBreaker.CircuitBreaker;
import com.lbw.Client.circuitBreaker.CircuitBreakerProvider;
import com.lbw.Client.rpcClient.RpcClient;
import com.lbw.Client.rpcClient.impl.NettyRpcClient;
import com.lbw.Client.serviceCenter.ServiceCenter;
import com.lbw.Client.serviceCenter.ZKServiceCenter;
import com.lbw.common.Message.RpcRequest;
import com.lbw.common.Message.RpcResponse;
import com.lbw.Client.retry.guavaRetry;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author lbwxxc
 * @date 2025/2/18 17:03
 * @description: 动态代理
 */
public class ClientProxy implements InvocationHandler {
    //传入参数service接口的class对象，反射封装成一个request

    private RpcClient rpcClient;
    private ServiceCenter serviceCenter;
    private CircuitBreakerProvider circuitBreakerProvider;
    public ClientProxy() throws InterruptedException {
        rpcClient = new NettyRpcClient();
        serviceCenter = new ZKServiceCenter();
        circuitBreakerProvider = new CircuitBreakerProvider();
    }

    //jdk动态代理，每一次代理对象调用方法，都会经过此方法增强（反射获取request对象，socket发送到服务端）
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //构建request
        RpcRequest request=RpcRequest.builder()
                .interfaceName(method.getDeclaringClass().getName())
                .methodName(method.getName())
                .params(args).paramType(method.getParameterTypes()).build();
        CircuitBreaker circuitBreaker = circuitBreakerProvider.getCircuitBreaker(method.getName());
        if (!circuitBreaker.allowRequest()) {

            return null;
        }
        //数据传输
        RpcResponse response;
        if (serviceCenter.checkRetry(request.getInterfaceName())) {
            response = new guavaRetry().sendServiceWithRetry(request, rpcClient);
        } else {
            response = rpcClient.sendRequest(request);
        }
        if (response.getCode() == 200) {
            circuitBreaker.recordSuccess();
        }
        if (response.getCode() == 500) {
            circuitBreaker.recordFailure();
        }
        return response.getData();
    }
    public <T>T getProxy(Class<T> clazz){
        Object o = Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{clazz}, this);
        return (T)o;
    }
}
